﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;

namespace MOM.Player
{
    [ScriptableType]
    public partial class Page : UserControl
    {
        #region Private Properties
        private MediaElement m_Media;
        private Rectangle m_BufferBar;
        private Rectangle m_DownloadBar;
        private Rectangle m_TimerBar;
        private Rectangle m_TimerBorder;
        private Rectangle m_TimerMarking;
        private Image m_ImagePlay;
        private Image m_ImagePrev;
        private Image m_ImageNext;
        private Image m_ImageVol;
        private Image m_ImageVolBg;
        private Image m_ImageShuffle;
        private Image m_ImageRepeat;
        private Storyboard m_Timeline;
        private TextBlock m_TimeTotal;
        private TextBlock m_TimeElapsed;
        private bool m_IsPlaying = false;
        private bool m_IsDownloaded = false;
        private int m_TrackPlayed = 0;
        private DateTime m_TrackStarted;
        private bool m_IsSelecting = false;
        private bool m_IsAdjustingVol = false;
        private string m_ImagePath;
        private CSS m_Css;
        private bool m_StatusShuffle = true;
        private bool m_StatusRepeat = true;
        #endregion

        public Page()
        {
            InitializeComponent();
        }

        [ScriptableMember]
        public event EventHandler<MediaEventArgs> MediaEnded;
        [ScriptableMember]
        public event EventHandler<MediaEventArgs> Next;
        [ScriptableMember]
        public event EventHandler<MediaEventArgs> Prev;
        [ScriptableMember]
        public event EventHandler<SwitchEventArgs> SetShuffle;
        [ScriptableMember]
        public event EventHandler<SwitchEventArgs> SetRepeat;

        public void Page_Loaded(object o, EventArgs e)
        {
            m_Media = (MediaElement)FindName("MediaPlayer");
            m_Media.BufferingProgressChanged += new RoutedEventHandler(Media_BufferingProgressChanged);
            m_Media.DownloadProgressChanged += new RoutedEventHandler(Media_DownloadProgressChanged);
            m_Media.MediaEnded += new RoutedEventHandler(Media_MediaEnded);
            m_Media.MediaOpened += new RoutedEventHandler(Media_MediaOpened);

            this.MouseMove += new MouseEventHandler(Canvas_MouseMove);
            this.MouseLeftButtonUp += new MouseButtonEventHandler(Canvas_MouseLeftButtonUp);

            m_TimerBorder = (Rectangle)FindName("TimerBorder");
            m_TimerBorder.MouseLeftButtonDown += new MouseButtonEventHandler(TimerBorder_MouseLeftButtonDown);

            m_ImagePlay = (Image)FindName("imgPlay");
            m_ImagePlay.MouseEnter += new MouseEventHandler(Button_MouseEnter);
            m_ImagePlay.MouseLeave += new MouseEventHandler(Button_MouseLeave);
            m_ImagePlay.MouseLeftButtonUp += new MouseButtonEventHandler(Play_MouseLeftButtonUp);

            m_ImagePrev = (Image)FindName("imgPrev");
            m_ImagePrev.MouseEnter += new MouseEventHandler(Button_MouseEnter);
            m_ImagePrev.MouseLeave += new MouseEventHandler(Button_MouseLeave);
            m_ImagePrev.MouseLeftButtonUp += new MouseButtonEventHandler(Prev_MouseLeftButtonUp);

            m_ImageNext = (Image)FindName("imgNext");
            m_ImageNext.MouseEnter += new MouseEventHandler(Button_MouseEnter);
            m_ImageNext.MouseLeave += new MouseEventHandler(Button_MouseLeave);
            m_ImageNext.MouseLeftButtonUp += new MouseButtonEventHandler(Next_MouseLeftButtonUp);

            m_ImageVol = (Image)FindName("imgVolume");
            m_ImageVolBg = (Image)FindName("imgVolumeBg");
            m_ImageVol.MouseLeftButtonDown += new MouseButtonEventHandler(ImageVol_MouseLeftButtonDown);
            m_ImageVol.MouseMove += new MouseEventHandler(ImageVol_MouseMove);
            m_ImageVolBg.MouseLeftButtonDown += new MouseButtonEventHandler(ImageVol_MouseLeftButtonDown);
            m_ImageVolBg.MouseMove += new MouseEventHandler(ImageVol_MouseMove);

            m_ImageShuffle = (Image)FindName("imgShuffle");
            m_ImageShuffle.MouseLeftButtonUp += new MouseButtonEventHandler(ImageShuffle_MouseLeftButtonUp);
            m_ImageShuffle.MouseEnter += new MouseEventHandler(Button_MouseEnter);
            m_ImageShuffle.MouseLeave += new MouseEventHandler(Button_MouseLeave);

            m_ImageRepeat = (Image)FindName("imgRepeat");
            m_ImageRepeat.MouseLeftButtonUp += new MouseButtonEventHandler(ImageRepeat_MouseLeftButtonUp);
            m_ImageRepeat.MouseEnter += new MouseEventHandler(Button_MouseEnter);
            m_ImageRepeat.MouseLeave += new MouseEventHandler(Button_MouseLeave);

            m_Timeline = (Storyboard)FindName("Timer");
            m_Timeline.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 300));
            m_Timeline.Completed += new EventHandler(Timer_Tick);

            m_TimerMarking = (Rectangle)FindName("TimerMarking");
            m_TimeTotal = (TextBlock)FindName("txtTimeTotal");
            m_TimeElapsed = (TextBlock)FindName("txtTimeElapsed");
            m_BufferBar = (Rectangle)FindName("BufferBar");
            m_DownloadBar = (Rectangle)FindName("DownloadBar");
            m_TimerBar = (Rectangle)FindName("TimerBar");

            m_Css = new CSS();
            m_Css.StyleLoaded += new System.Net.DownloadStringCompletedEventHandler(Css_StyleLoaded);
            m_ImagePath = GetAppPath() + "/Images/green";

            HtmlPage.RegisterScriptableObject("basic", this);
        }

        #region VOLUME
        private void ImageVol_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            m_IsAdjustingVol = true;
            ImageVol_MouseMove(sender, e);
        }

        private void ImageVol_MouseMove(object sender, MouseEventArgs e)
        {
            if (m_IsAdjustingVol && !m_IsSelecting)
            {
                int imgLeft = Convert.ToInt32((double)m_ImageVol.GetValue(Canvas.LeftProperty));
                double posX = e.GetPosition(null).X - imgLeft;
                double volHeight = (double)m_ImageVol.GetValue(FrameworkElement.ActualHeightProperty);
                double volWidth = (double)m_ImageVol.GetValue(FrameworkElement.ActualWidthProperty);

                RectangleGeometry g = new RectangleGeometry();
                g.Rect = new Rect(0, 0, posX, volHeight);
                m_ImageVol.Clip = g;

                double vol = (posX + 4) / volWidth;
                m_Media.Volume = vol;
            }
        }
        #endregion

        #region TIMESLIDER
        private void Canvas_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            m_IsAdjustingVol = false;

            if (m_IsSelecting)
            {
                m_IsSelecting = false;

                if (m_IsDownloaded && m_TimerMarking.Width <= m_DownloadBar.Width)
                {
                    m_TimerBar.Width = m_TimerMarking.Width;
                    m_Media.Position = TimeSpan.FromSeconds(m_Media.NaturalDuration.TimeSpan.TotalSeconds * ((double)m_TimerBar.Width / (double)this.Width));
                }

                m_TimerMarking.Width = 0;
            }
        }

        private void TimerBorder_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            m_IsSelecting = true;
            m_TimerMarking.Width = e.GetPosition(null).X;
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (m_IsSelecting)
            {
                m_TimerMarking.Width = e.GetPosition(null).X;
            }
        }
        #endregion

        #region BUTTON EVENTS
        private void ImageShuffle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            m_StatusShuffle = !m_StatusShuffle;
            if (SetShuffle != null)
                SetShuffle(sender, new SwitchEventArgs(m_StatusShuffle));
        }

        private void ImageRepeat_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            m_StatusRepeat = !m_StatusRepeat;
            if (SetRepeat != null)
                SetRepeat(sender, new SwitchEventArgs(m_StatusRepeat));
        }

        private void Prev_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            if (Prev != null)
                Prev(sender, new MediaEventArgs(false, m_TrackStarted, m_TrackPlayed));
        }

        private void Next_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            if (Next != null)
                Next(sender, new MediaEventArgs(false, m_TrackStarted, m_TrackPlayed));
        }

        private void Play_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            if (m_IsPlaying)
            {
                Pause();
            }
            else
            {
                Play();
            }
        }

        private void Button_MouseLeave(object sender, EventArgs e)
        {
            Image img = (Image)sender;
            if ((img.Name == "imgShuffle" && m_StatusShuffle) || (img.Name == "imgRepeat" && m_StatusRepeat))
                return;
            string source = ((BitmapImage)img.GetValue(Image.SourceProperty)).UriSource.AbsoluteUri;
            source = source.Replace("_hover", "");
            SetImage(img, source);
        }

        private void Button_MouseEnter(object sender, MouseEventArgs e)
        {
            Image img = (Image)sender;
            string source = ((BitmapImage)img.GetValue(Image.SourceProperty)).UriSource.AbsoluteUri;
            if (source.IndexOf("_hover") == -1)
            {
                int end = source.LastIndexOf('.');
                source = source.Substring(0, end) + "_hover.png";
                SetImage(img, source);
            }
        }
        #endregion

        #region TIMER
        private void Timer_Tick(object sender, EventArgs e)
        {
            if (m_IsPlaying)
            {
                m_TrackPlayed += Convert.ToInt32(m_Timeline.Duration.TimeSpan.TotalMilliseconds);
                if (m_IsDownloaded)
                {
                    try
                    {
                        double pos = m_Media.Position.TotalMilliseconds;
                        double total = m_Media.NaturalDuration.TimeSpan.TotalMilliseconds;
                        m_TimerBar.Width = Convert.ToInt32(this.Width * (pos / total));
                        m_TimeElapsed.Text = TimeSpanToString(m_Media.Position);
                    }
                    catch { }
                }
            }
            m_Timeline.Begin();
        }
        #endregion

        #region Media
        private void Media_MediaEnded(object sender, EventArgs e)
        {
            m_IsDownloaded = false;
            Pause();
            if (MediaEnded != null)
                MediaEnded(sender, new MediaEventArgs(true, m_TrackStarted, m_TrackPlayed));
        }

        private void Media_MediaOpened(object sender, EventArgs e)
        {
            m_IsDownloaded = true;
            m_TimeTotal.Text = TimeSpanToString(m_Media.NaturalDuration.TimeSpan);
            m_TimeTotal.SetValue(Canvas.LeftProperty, this.Width - m_TimeTotal.ActualWidth);
        }

        private void Media_DownloadProgressChanged(object sender, EventArgs e)
        {
            m_DownloadBar.Width = Convert.ToInt32(this.Width * m_Media.DownloadProgress);
        }

        private void Media_BufferingProgressChanged(object sender, EventArgs e)
        {
            m_BufferBar.Width = Convert.ToInt32((this.Width / (double)4) * m_Media.BufferingProgress);
            if (m_Media.BufferingProgress >= 1)
                m_BufferBar.Width = 0;
        }
        #endregion

        #region CSS
        private void Css_StyleLoaded(object sender, System.Net.DownloadStringCompletedEventArgs e)
        {
            try
            {
                m_Css.ApplyToCanvas(parentCanvas);
            }
            catch { }
            SetImage(m_ImagePlay, m_ImagePath + "/player_play.png");
            SetImage(m_ImageNext, m_ImagePath + "/player_next.png");
            SetImage(m_ImagePrev, m_ImagePath + "/player_prev.png");
            SetImage(m_ImageVol, m_ImagePath + "/player_volume_on.png");
            SetImage(m_ImageVolBg, m_ImagePath + "/player_volume_bg.png");
            if (!m_StatusShuffle)
                SetImage(m_ImageShuffle, m_ImagePath + "/player_shuffle.png");
            else
                SetImage(m_ImageShuffle, m_ImagePath + "/player_shuffle_hover.png");
            if (!m_StatusRepeat)
                SetImage(m_ImageRepeat, m_ImagePath + "/player_repeat.png");
            else
                SetImage(m_ImageRepeat, m_ImagePath + "/player_repeat_hover.png");
        }
        #endregion

        #region Public Methods
        [ScriptableMember]
        public void Load(string url, bool forced)
        {
            if (forced && MediaEnded != null)
            {
                MediaEnded(m_Media, new MediaEventArgs(false, m_TrackStarted, m_TrackPlayed));
            }

            if (!String.IsNullOrEmpty(url))
            {
                m_TimeTotal.Text = "--:--";
                m_TimeElapsed.Text = "--:--";
                m_IsDownloaded = false;
                m_IsPlaying = false;
                m_Media.Source = new Uri(url);
                m_TrackStarted = DateTime.Now.ToUniversalTime();
                m_TrackPlayed = 0;
                Play();
            }
        }

        [ScriptableMember]
        public void MuteSwitch()
        {
            m_Media.IsMuted = !m_Media.IsMuted;
        }

        [ScriptableMember]
        public void Play()
        {
            if (m_Media.Source != null && !String.IsNullOrEmpty(m_Media.Source.OriginalString))
            {
                m_IsPlaying = true;
                m_Media.Play();
                m_Timeline.Begin();
                string source = ((BitmapImage)m_ImagePlay.GetValue(Image.SourceProperty)).UriSource.AbsoluteUri;
                source = source.Replace("_play", "_pause");
                SetImage(m_ImagePlay, source);
            }
        }

        [ScriptableMember]
        public void Pause()
        {
            m_IsPlaying = false;
            m_Media.Pause();
            m_Timeline.Stop();
            string source = ((BitmapImage)m_ImagePlay.GetValue(Image.SourceProperty)).UriSource.AbsoluteUri;
            source = source.Replace("_pause", "_play");
            SetImage(m_ImagePlay, source);
        }
        
        [ScriptableMember]
        public void SetTheme(string theme)
        {
            m_ImagePath = GetAppPath() + "/Images/" + theme;
            m_Css.LoadStylesheet(GetAppPath() + "/Css/themes/" + theme + ".css");
        }
        #endregion

        private void SetImage(Image img, string source)
        {
            BitmapImage bmp = new BitmapImage(new Uri(source, UriKind.Absolute));
            img.SetValue(Image.SourceProperty, bmp);
        }

        private string GetAppPath()
        {
       		string path = HtmlPage.Document.DocumentUri.ToString();
       		path = path.Substring(0, path.LastIndexOf('/')).TrimEnd('/');
       		return path;
        }
        
        private string TimeSpanToString(TimeSpan ts)
        {
            return ((ts.Hours > 0) ? ts.Hours.ToString() + ":" : "")
                + ((ts.Minutes < 10) ? "0" : "") + ts.Minutes.ToString() + ":"
                + ((ts.Seconds < 10) ? "0" : "") + ts.Seconds.ToString();
        }
    }
}
